package com.server.database;

import com.eureka.bean.AbsInstance;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * Description:
 *
 * @author weiruibai.vendor
 * Date: 2023/1/29 15:55
 */
@Slf4j
@Data
public class DataSource {

    /**
     * 存储实例信息
     */
    private static final ConcurrentHashMap<String, AbsInstance> INSTANCE_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();

    /**
     * 一个实例，可以部署在多个服务器上，为了实现负载均衡，根据组分类
     */
    private static final ConcurrentHashMap<String, List<AbsInstance>> INSTANCE_GROUP_BY_NAME = new ConcurrentHashMap<>();

    public static ConcurrentHashMap<String, AbsInstance> getInstanceConcurrentHashMap() {
        return INSTANCE_CONCURRENT_HASH_MAP;
    }

    public static ConcurrentHashMap<String, List<AbsInstance>> getInstanceGroupByName() {
        return INSTANCE_GROUP_BY_NAME;
    }

    public synchronized static boolean add(AbsInstance instance) {
        try {
            if (instance == null) {
                return false;
            }
            String key = String.format("%s%s", instance.getIp(), instance.getPort());
            INSTANCE_CONCURRENT_HASH_MAP.put(key, instance);
            addInstanceGroupByName(instance);
        } catch (Exception e) {
            log.error("{}", e);
            return false;
        }
        return true;
    }

    private static void addInstanceGroupByName(AbsInstance instance) {
        List<AbsInstance> instanceList = INSTANCE_GROUP_BY_NAME.get(instance.getGroupName());
        if (CollectionUtils.isEmpty(instanceList)) {
            instanceList = new ArrayList<>();
            instanceList.add(instance);
            INSTANCE_GROUP_BY_NAME.put(instance.getGroupName(), instanceList);
        } else {
            Set<String> collect = instanceList
                    .stream()
                    .map(obj -> String.format("%s%s", obj.getIp(), obj.getPort()))
                    .collect(Collectors.toSet());
            String key = String.format("%s%s", instance.getIp(), instance.getPort());
            if (CollectionUtils.isEmpty(collect) || !collect.contains(key)) {
                instanceList.add(instance);
            }
        }
    }

    public synchronized static boolean remove(AbsInstance instance) {
        try {
            if (instance == null) {
                return false;
            }
            String key = String.format("%s%s", instance.getIp(), instance.getPort());
            INSTANCE_CONCURRENT_HASH_MAP.remove(key);
            /**
             * 移除INSTANCE_GROUP_BY_NAME中的实例
             */
            List<AbsInstance> absInstances = INSTANCE_GROUP_BY_NAME.get(instance.getGroupName());
            for (int i = 0; i < absInstances.size(); i++) {
                AbsInstance obj = absInstances.get(i);
                if (key.equals(String.format("%s%s", obj.getIp(), obj.getPort()))) {
                    absInstances.remove(i);
                    break;// 退出
                }
            }
        } catch (Exception e) {
            log.error("{}", e);
            return false;
        }
        return true;
    }

    public static List<AbsInstance> getInstances() {
        return INSTANCE_CONCURRENT_HASH_MAP.values().stream().collect(Collectors.toList());
    }

    public static void printInstanceByGroup() {
        for (Map.Entry<String, List<AbsInstance>> m : INSTANCE_GROUP_BY_NAME.entrySet()) {
            log.info("group: {}", m.getKey());
            List<AbsInstance> list = m.getValue();
            list.stream().forEach(obj -> {
                log.info("instances: {}", obj);
            });
        }
    }
}
